class Grid{
  private Cell[][] grid;
  private int gw = 25;
  private int gh = 25;
  private int cellSize = 5;
  private int margin = 20;

  public Grid(){
    grid = new Cell[gw][gh];

    for (int i=0; i<gw; i++){
      for (int j=0; j<gh; j++){
        grid[i][j] = new Cell();
        if ((i==0)||(j==0)||(i==gw-1)||(j==gh-1)){
          grid[i][j].Birth();
          grid[i][j].Update();
          grid[i][j].Lock();
        }
      }
    }
    QrLocation(0,0);
    QrLocation(0,gh-9);
    QrLocation(gw-9,0);
    //QrMiniLocation(21,21);
    QrAlternate(7,8,7,21);
    QrAlternate(8,7,21,7);
  }

  public void QrLocation(int x, int y){
    for (int i=0; i<9; i++){
      for (int j=0; j<9; j++){
        if ((i==0)||(i==8)||(j==0)||(j==8)){
          grid[x+i][y+j].Birth();
          grid[x+i][y+j].Update();
          grid[x+i][y+j].Lock();
          continue;
        }
        if ((i==1)||(i==7)||(j==1)||(j==7)){
          grid[x+i][y+j].Death();
          grid[x+i][y+j].Update();
          grid[x+i][y+j].Lock();
          continue;
        }
        if ((i==2)||(i==6)||(j==2)||(j==6)){
          grid[x+i][y+j].Birth();
          grid[x+i][y+j].Update();
          grid[x+i][y+j].Lock();
          continue;
        }
        grid[x+i][y+j].Death();
        grid[x+i][y+j].Update();
        grid[x+i][y+j].Lock();
        continue;
      }
    }
  }
  
  public void QrMiniLocation(int x, int y){
    for (int i=0; i<5; i++){
      for (int j=0; j<5; j++){
        if ((i==0)||(i==4)||(j==0)||(j==4)){
          grid[x+i][y+j].Death();
          grid[x+i][y+j].Update();
          grid[x+i][y+j].Lock();
          continue;
        }
        if ((i==1)||(i==3)||(j==1)||(j==3)){
          grid[x+i][y+j].Birth();
          grid[x+i][y+j].Update();
          grid[x+i][y+j].Lock();
          continue;
        }
        if ((i==2)&&(j==2)){
          grid[x+i][y+j].Death();
          grid[x+i][y+j].Update();
          grid[x+i][y+j].Lock();
          continue;
        }
        grid[x+i][y+j].Death();
        grid[x+i][y+j].Update();
        grid[x+i][y+j].Lock();
        continue;
      }
    }
  }

  public void QrAlternate(int sx, int sy, int ex, int ey){
    if (sx==ex){
      // vertical
      for (int i=min(sy,ey); i<=max(sy,ey); i++){
        if (((max(sy,ey)-i)%2) == 0){
          grid[sx][i].Birth();
        }
        else{
          grid[sx][i].Death();
        }
        grid[sx][i].Update();
        grid[sx][i].Lock();
      }
      return;
    }

    if (sy==ey){
      // vertical
      for (int i=min(sx,ex); i<=max(sx,ex); i++){
        if (((max(sx,ex)-i)%2) == 0){
          grid[i][sy].Birth();
        }
        else{
          grid[i][sy].Death();
        }
        grid[i][sy].Update();
        grid[i][sy].Lock();
      }
      return;
    }
  }

  public void Random(){
    for (int i = 0; i < gw * gh * 0.5; i++) { 
      grid[(int)random(gw)][(int)random(gh)].Birth(); 
    } 
  }

  public void Draw(){
    for (int i=0; i<gw; i++){
      for (int j=0; j<gh; j++){
        if (grid[i][j].IsAlive()){
          fill(255);
        }
        else{
          fill(0);
        }
        rect((i*5)+margin,(j*5)+margin,5,5);
      }
    }
  }

  public void Evolve(){
    for (int i=0; i<gw; i++){
      for (int j=0; j<gh; j++){
        grid[i][j].Evolve(AliveNeighbours(i,j));
      }
    }
  }

  public void Update(){
    for (int i=0; i<gw; i++){
      for (int j=0; j<gh; j++){
        grid[i][j].Update();
      }
    }
  }

  public int AliveNeighbours(int x, int y){
    int res = 0;
    for (int i=-1; i<=1; i++){
      for (int j=-1; j<=1; j++){
        if (((x+i)>=0)&&((x+i)<gw)&&((y+j)>=0)&&((y+j)<gh)){
          if (grid[(x+i)][(y+j)].IsAlive()){
            res ++;
          }
        }
      }
    }
    return res;
  }
}
